﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace AgLux
{
    /// <summary>
    /// Represents a component that displays a task.
    /// </summary>

    public class Task : Component
    {
        protected TextBlock _question;
        protected Canvas _answers, _taskPanel, _previous, _ok, _next;

        protected GradientStop _previousColor1, _previousColor2, _previousColor3;
        protected GradientStop _okColor1, _okColor2, _okColor3;
        protected GradientStop _nextColor1, _nextColor2, _nextColor3;

        protected List<Question> _questions;
        protected int _index, _points;
        protected bool _previousEnabled, _okEnabled, _nextEnabled;

        /// <summary>
        /// Initializes a new instance of the Task class.
        /// </summary>

        /// <param name="questions">
        /// The list of Question objects.
        /// </param>

        public Task(List<Question> questions)
            : base()
        {
            _question = (TextBlock)_resource.FindName("text");
            _answers = (Canvas)_resource.FindName("task");

            _taskPanel = (Canvas)_resource.FindName("taskPanel");
            _previous = (Canvas)_resource.FindName("previous");
            _ok = (Canvas)_resource.FindName("ok");
            _next = (Canvas)_resource.FindName("next");

            _previousColor1 = (GradientStop)_resource.FindName("previousColor1");
            _previousColor2 = (GradientStop)_resource.FindName("previousColor2");
            _previousColor3 = (GradientStop)_resource.FindName("previousColor3");

            _okColor1 = (GradientStop)_resource.FindName("okColor1");
            _okColor2 = (GradientStop)_resource.FindName("okColor2");
            _okColor3 = (GradientStop)_resource.FindName("okColor3");

            _nextColor1 = (GradientStop)_resource.FindName("nextColor1");
            _nextColor2 = (GradientStop)_resource.FindName("nextColor2");
            _nextColor3 = (GradientStop)_resource.FindName("nextColor3");

            _questions = questions;
            _index = _points = 0;
            _previousEnabled = _okEnabled = _nextEnabled = false;

            _previous.MouseLeftButtonDown += new MouseEventHandler(PreviousPress);
            _ok.MouseLeftButtonDown += new MouseEventHandler(OkPress);
            _next.MouseLeftButtonDown += new MouseEventHandler(NextPress);

            _taskPanel.Visibility = Visibility.Visible;
            foreach (Question question in _questions)
            {
                question.AnswerMarked += new EventHandler(AnswerMark);
                question.AnswerUnmarked += new EventHandler(AnswerUnmark);
            }
        }

        /// <summary>
        /// Prepare to display the component.
        /// </summary>

        /// <param name="width">
        /// The width of the canvas on which the component will be displayed.
        /// </param>

        public override void Prepare(double width)
        {
            Width = _screen.Width = _question.Width = _answers.Width = width;
            foreach (Question question in _questions)
            {
                question.Prepare(width);
            }
            LoadQuestion();
        }

        /// <summary>
        /// Loads the question at the current index.
        /// </summary>

        protected virtual void LoadQuestion()
        {
            _question.Text = _index + 1 + ": " + _questions[_index].Text + "?";
            _answers.Children.Clear();
            _answers.Children.Add(_questions[_index]);

            _screen.Height = _question.ActualHeight;
            _answers.Height = _questions[_index].Height;
            Height = _screen.Height + _answers.Height + _taskPanel.Height + 10;

            _answers.SetValue(Canvas.TopProperty, _screen.Height + 5);
            _taskPanel.SetValue(Canvas.TopProperty, _screen.Height + _answers.Height + 10);
        }

        /// <summary>
        /// Displays the task result.
        /// </summary>

        protected virtual void ShowResult()
        {
            _question.Text = "CORRECT ANSWERS: " + _points + " / " + _questions.Count;
            _answers.Children.Clear();

            _screen.Height = _question.ActualHeight;
            Height = _screen.Height + _taskPanel.Height + 5;
            _taskPanel.SetValue(Canvas.TopProperty, _screen.Height + 5);
        }

        /// <summary>
        /// Enables the previous button.
        /// </summary>

        protected virtual void EnablePrevious()
        {
            _previousColor1.Color = _previousColor3.Color = Color.FromRgb(150, 150, 150);
            _previousColor2.Color = Color.FromRgb(255, 255, 255);
            _previousEnabled = true;
        }

        /// <summary>
        /// Disables the previous button.
        /// </summary>

        protected virtual void DisablePrevious()
        {
            _previousColor1.Color = _previousColor2.Color = _previousColor3.Color = Colors.Black;
            _previousEnabled = false;
        }

        /// <summary>
        /// Enables the ok button.
        /// </summary>

        protected virtual void EnableOk()
        {
            _okColor1.Color = _okColor3.Color = Color.FromRgb(150, 150, 150);
            _okColor2.Color = Color.FromRgb(255, 255, 255);
            _okEnabled = true;
        }

        /// <summary>
        /// Disables the ok button.
        /// </summary>

        protected virtual void DisableOk()
        {
            _okColor1.Color = _okColor2.Color = _okColor3.Color = Colors.Black;
            _okEnabled = false;
        }

        /// <summary>
        /// Enables the next button.
        /// </summary>

        protected virtual void EnableNext()
        {
            _nextColor1.Color = _nextColor3.Color = Color.FromRgb(150, 150, 150);
            _nextColor2.Color = Color.FromRgb(255, 255, 255);
            _nextEnabled = true;
        }

        /// <summary>
        /// Disables the next button.
        /// </summary>

        protected virtual void DisableNext()
        {
            _nextColor1.Color = _nextColor2.Color = _nextColor3.Color = Colors.Black;
            _nextEnabled = false;
        }

        /// <summary>
        /// Occurs when an answer is marked.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        protected virtual void AnswerMark(object sender, EventArgs args)
        {
            EnableOk();
        }

        /// <summary>
        /// Occurs when an answer is unmarked.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        protected virtual void AnswerUnmark(object sender, EventArgs args)
        {
            DisableOk();
        }

        /// <summary>
        /// Occurs when the previous button is pressed.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The MouseEventArgs that contains the event data.
        /// </param>

        protected virtual void PreviousPress(object sender, MouseEventArgs args)
        {
            if (_previousEnabled)
            {
                _index--;
                DisableOk();
                EnableNext();

                if (_index == 0)
                {
                    DisablePrevious();
                }

                LoadQuestion();
            }
        }

        /// <summary>
        /// Occurs when the ok button is pressed.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The MouseEventArgs that contains the event data.
        /// </param>

        protected virtual void OkPress(object sender, MouseEventArgs args)
        {
            if (_okEnabled)
            {
                _points += _questions[_index].Correct();
                DisableOk();
                EnableNext();
            }
        }

        /// <summary>
        /// Occurs when the next button is pressed.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The MouseEventArgs that contains the event data.
        /// </param>

        protected virtual void NextPress(object sender, MouseEventArgs args)
        {
            if (_nextEnabled)
            {
                _index++;
                EnablePrevious();

                if (_index == _questions.Count)
                {
                    DisableOk();
                    DisableNext();
                    ShowResult();
                }

                else
                {
                    if (_questions[_index].IsCorrected)
                    {
                        DisableOk();
                        EnableNext();
                    }
                    else if (_questions[_index].IsAnswered)
                    {
                        EnableOk();
                        DisableNext();
                    }
                    else
                    {
                        DisableOk();
                        DisableNext();
                    }

                    LoadQuestion();
                }
            }
        }
    }
}
